﻿//
// Created by user_temp_1 on 2023/6/14.
//

#ifndef FAST_EXPERIENCE_UTILS_WARP_HPP
#define FAST_EXPERIENCE_UTILS_WARP_HPP

#include <map>
#include <ostream>
#include "log.h"
#include <tuple>
#include <array>
#include <utility>
#include <string>
#include <queue>
#include <unordered_map>
#include <algorithm>
#include <memory>
#include <ostream>
#include <typeindex>
#include <iostream>
#include <functional>
#include <boost/tuple/tuple.hpp>
#include <boost/utility.hpp>
#include <boost/unordered_map.hpp>
#include <boost/any.hpp>
#include <type_traits>

#include <thread>

#ifdef NO_USE_MODULE

#ifdef WIN32

#include <Windows.h>


typedef CRITICAL_SECTION pthread_mutex_t;

#else

#include <pthread.h>

#endif
#endif

// uint32_t
// 自旋锁
#include <atomic>
// 信号量
#include <mutex>
#include <condition_variable>
#include <shared_mutex>
#include <cstddef>

#ifdef NO_USE_MODULE

/**
         * @brief windows下为临界区:	通过对多线程的串行化来访问公共资源或一段代码，速度快，适合控制数据访问
         * 		  linux下为互斥锁:	为协调共同对一个共享资源的单独访问而设计的
         */
        class Mutex /*: public NonCopyable*/ {
        public:
            Mutex()
                    : _threadId(0) {
#ifdef WIN32
                InitializeCriticalSection(&_mutex);
#else
                pthread_mutex_init(&_mutex, NULL);
#endif
            }

            ~Mutex() {
#ifdef WIN32
                DeleteCriticalSection(&_mutex);
#else
                pthread_mutex_destroy(&_mutex);
#endif
            }

            void lock() {
#ifdef WIN32
                EnterCriticalSection(&_mutex);
            _threadId = static_cast<uint32_t>(GetCurrentThreadId());
#else
                pthread_mutex_lock(&_mutex);
                _threadId = static_cast<uint32_t>(pthread_self());
#endif
            }

            void unlock() {
                _threadId = 0;
#ifdef WIN32
                LeaveCriticalSection(&_mutex);
#else
                pthread_mutex_unlock(&_mutex);
#endif
            }

            pthread_mutex_t *getMutex() {
                return &_mutex;
            }

        private:
            uint32_t _threadId;             // 获取当前线程id
            pthread_mutex_t _mutex;         // 锁
        };

#endif


/**
 * @brief 正则表达式
 */
namespace fast::util{


    class CheckStr {
        enum type {
            phone,
            tel,
            card,
            pwd,
            postal,
            QQ,
            email,
            money,
            URL,
            IP,
            date,
            number,
            english,
            chinese,
            lower,
            upper,
            HTML
        };

        static std::string getType(type type) {
            switch (type) {
                case phone :   //手机号码
                    return R"(^1[3|4|5|6|7|8|9][0-9]{9}$)";
                case tel :     //座机
                    return R"(^(0\d{2,3}-\d{7,8})(-\d{1,4})?$)";
                case card :    //身份证
                    return R"((^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$))";
                case pwd :     //密码以字母开头，长度在6~18之间，只能包含字母、数字和下划线
                    return "^[a-zA-Z]\\w{5,17}$";
                case postal :  //邮政编码
                    return R"([1-9]\d{5}(?!\d))";
                case QQ :      //QQ号
                    return "^[1-9][0-9]{4,9}$";
                case email :   //邮箱
                    return R"(^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$)";
                case money :   //金额(小数点2位)
                    return R"(^\d*(?:\.\d{0,2})?$)";
                case URL :     //网址
                    return R"((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?)";
                case IP :      //IP
                    return R"(((?:(?:25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d?\d)))";
                case date :    //日期时间
                    return R"(^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/.test(str) || ^(\d{4})\-(\d{2})\-(\d{2})$)";
                case number :  //数字
                    return "^[0-9]$";
                case english : //英文
                    return "^[a-zA-Z]+$";
                case chinese : //中文
                    return R"(^[\\u4E00-\\u9FA5]+$)";
                case lower :   //小写
                    return "^[a-z]+$";
                case upper :   //大写
                    return "^[A-Z]+$";
                case HTML :    //HTML标记
                    return R"(<("[^"]*"|'[^']*'|[^'">])*>)";
                default:
                    return "";
            }
        }

    };//CheckStr

/**
*  PrintType(b1);
PrintType(b2);
PrintType(b3);
PrintType(BaseClassForTest());
*/
    template<typename T>
    void PrintType(T &&param) {
        using namespace std;
        using boost::typeindex::type_id_with_cvr;

        // 利用Boost库打印模板推导出来的 T 类型
        LOG_DEBUG << "T type：" << type_id_with_cvr<T>().pretty_name();

        // 利用Boost库打印形参的类型
        LOG_DEBUG << "param type:" << type_id_with_cvr<decltype(param)>().pretty_name();
    }


    class Any {
    public:
        Any() : m_typeIndex(std::type_index(typeid(void))) {}

        Any(Any &other) : m_basePtr(other.clone()), m_typeIndex(other.m_typeIndex) {}

        Any(Any &&other) : m_basePtr(std::move(other.m_basePtr)), m_typeIndex(other.m_typeIndex) {}

        // 创建智能指针时，对于一般的类型，通过std::decay来移除引用和cv符，从而获得原始类型.
        template<typename U, class = typename std::enable_if<!std::is_same<typename std::decay<U>::type, Any>::value,
                U>::type>
        Any(U &&value) : m_basePtr(new Derived<typename std::decay<U>::type>(std::forward<U>(value))),
                         m_typeIndex(std::type_index(typeid(typename std::decay<U>::type))) {}

        bool isNull() const {
            return !bool(m_basePtr);
        }

        template<typename U>
        bool is() const {
            return m_typeIndex == std::type_index(typeid(U));
        }

        // 将Any转换为实际的类型.
        template<typename U>
        U &anyCast() {
            if (!is<U>()) {
                std::cout << "Can not cast " << typeid(U).name() << " to " << m_typeIndex.name() << std::endl;
                throw std::bad_cast();
            }

            auto dervied = dynamic_cast<Derived <U> *>(m_basePtr.get());
            return dervied->m_value;
        }

        Any &operator=(const Any &other) {
            if (m_basePtr == other.m_basePtr) {
                return *this;
            }

            m_basePtr = other.clone();
            m_typeIndex = other.m_typeIndex;
            return *this;
        }

    private:
        class Base;

        using BasePtr = std::unique_ptr<Base>;

        class Base {
        public:
            virtual ~Base() {}

            virtual BasePtr clone() const = 0;
        };

        template<typename T>
        class Derived : public Base {
        public:
            template<typename U>
            Derived(U &&value) : m_value(std::forward<U>(value)) {}

            virtual BasePtr clone() const {
                return BasePtr(new Derived<T>(m_value));
            }

            T m_value;
        };

        BasePtr clone() const {
            if (m_basePtr != nullptr) {
                return m_basePtr->clone();
            }
            return nullptr;
        }

        BasePtr m_basePtr;
        std::type_index m_typeIndex;
    };

    class IocContainer {
    public:
        IocContainer() = default;

        IocContainer(const IocContainer &) = delete;

        IocContainer &operator=(const IocContainer &) = delete;

        template<typename T, typename Depend, typename... Args>
        typename std::enable_if<!std::is_base_of<T, Depend>::value>::type registerType(const std::string &key) {
            // 通过闭包擦除参数类型
            std::function<T *(Args...)> func = [](Args... args) { return new T(new Depend(args...)); };
            registerType(key, func);
        }

        template<typename T, typename Depend, typename... Args>
        typename std::enable_if<std::is_base_of<T, Depend>::value>::type registerType(const std::string &key) {
            // 通过闭包擦除参数类型
            std::function<T *(Args...)> func = [](Args... args) { return new Depend(args...); };
            registerType(key, func);
        }

        template<typename T, typename... Args>
        void registerSimple(const std::string &key) {
            std::function<T *(Args...)> func = [](Args... args) { return new T(args...); };
            registerType(key, func);
        }

        template<typename T, typename... Args>
        std::shared_ptr<T> resolveShared(const std::string &key, Args... args) {
            T *t = resolve<T>(key, args...);
            return std::shared_ptr<T>(t);
        }

        template<typename T, typename... Args>
        T *resolve(const std::string &key, Args... args) {
            auto iter = m_creatorMap.find(key);
            if (iter != m_creatorMap.end()) {
                Any resolver = iter->second;
                std::function<T *(Args...)> func = resolver.anyCast<std::function<T *(Args...) >>();
                return func(args...);
            }

            return nullptr;
        }

    private:
        void registerType(const std::string &key, Any constructor) {
            auto iter = m_creatorMap.find(key);
            if (iter != m_creatorMap.end()) {
                std::string errorString = key + " key has already exist.";
                throw std::invalid_argument(errorString);
            }

            // 通过Any擦除不同类型的构造器
            m_creatorMap.emplace(key, constructor);
        }

    private:
        std::unordered_map<std::string, Any> m_creatorMap;
    };


/**
* @note
* map<string, int>::key_type  v1; //此时key_type的v1类型是string
* map<string, int>::mapped_type  v2; //此时mapped_type的v2类型是int
* map<string, int>::value_type  v3; //此时value_type的v3类型是pair<const string, int>，注意pair键值对中第一个元素的类型有const(不可修改).
*/
    class MapUtil {
    public:

        /**
         *@brief 给定一个映射和一个键，返回对应于映射中的键的值，如果键不存在于映射中，则返回给定的默认值。
         *@code <pre>
         *
         *  MapUtil map_util;
         *
         *  std::map<std::string, std::string> map{
         *	    {"this", "100"},
         *  	{"can", "100"},
         *      {"be", "100"},
         *      {"const", "100"},
         *	};
         *
         *	auto default_value = map_util.GetDefault(map, "undefined");
         *
         *	LOG_INFO << typeid(default_value).name();
         *
         *
         * </pre>
         */
        template<typename Map, typename Key>
        static typename Map::mapped_type GetDefault(const Map &map, const Key &key) {
            auto pos = map.find(key);
            return (pos != map.end()) ? (pos->second) : (typename Map::mapped_type{});
        }

        /**
        *@brief 给定一个映射和一个键，返回对映射中与键对应的值的引用，如果映射中不存在该键，则返回给定的默认引用。
        *@code <pre>
        *
        *  MapUtil map_util;
        *
        *  std::map<std::string, std::string> map{
        *	  {"this", "100"},
        *  	  {"can", "100"},
        *      {"be", "100"},
        *      {"const", "100"},
        *	};
        *
        *  std::string mapped_type_value = "abcd";
        *  auto mapped_type_default_value = map_util.GetRefDefault(map, "undefined", mapped_type_value);
        *
        *  LOG_INFO << typeid(mapped_type_default_value).name();
        *
        *  LOG_INFO << mapped_type_default_value;
        *
        *  if (mapped_type_default_value == mapped_type_value) {
        *	 LOG_INFO << &mapped_type_default_value << "value is equal,but memory address not equal" << &mapped_type_value;
        *  }
        * </pre>
        */
        template<class Map, typename Key = typename Map::key_type>
        static const typename Map::mapped_type &GetRefDefault(
                const Map &map, const Key &key, const typename Map::mapped_type &dflt) {
            auto pos = map.find(key);
            return (pos != map.end() ? pos->second : dflt);
        }

        /**
         * 传递临时默认值会在返回时返回一个悬空引用，生命周期延长被间接破坏了。
         * 调用者必须确保默认值比 GetRefDefault() 返回的引用生命周期长。
         */
        template<class Map, typename Key = typename Map::key_type>
        static const typename Map::mapped_type &GetRefDefault(
                const Map &map, const Key &key, typename Map::mapped_type &&dflt) = delete;

        template<class Map, typename Key = typename Map::key_type>
        static const typename Map::mapped_type &GetRefDefault(
                const Map &map,
                const Key &key,
                const typename Map::mapped_type &&dflt) = delete;

        /**
         *@brief 给定一个映射和一个键，返回一个指向对应于映射中键的值的指针，如果键不存在于映射中，则返回 nullptr。
         *@code <pre>
         *
         *  MapUtil map_util;
         *
         *  std::map<std::string, std::string> map{
         *	    {"this", "100"},
         *  	{"can", "100"},
         *      {"be", "100"},
         *      {"const", "100"},
         *	};
         *
         *  // 默认 auto 带有const
         *  auto *const_ptr= map_util.GetConstPtr(map, "this");
         *
         * </pre>
         */
        template<class Map, typename Key = typename Map::key_type>
        static const auto *GetConstPtr(const Map &map, const Key &key) {
            auto pos = map.find(key);
            return (pos != map.end() ? &pos->second : nullptr);
        }

        /**
         *@brief 非const 获取 ptr
         *@code <pre>
         *
         *  MapUtil map_util;
         *
         *  std::map<std::string, std::string> map{
         *	  {"this", "100"},
         *  	  {"can", "100"},
         *      {"be", "100"},
         *      {"const", "100"},
         *	};
         *
         *  auto *ptr = map_util.GetPtr(map, "this");
         *
         *  *ptr = "200";
         *
         *  LOG_INFO << map["this"];
         * </pre>
         */
        template<class Map, typename Key = typename Map::key_type>
        static auto *GetPtr(Map &map, const Key &key) {
            auto pos = map.find(key);
            return (pos != map.end() ? &pos->second : nullptr);
        }

        template<class Map, typename Key = typename Map::key_type>
        static void printfMap(Map &map, const Key &key) {
            for (const auto &item: map) {

                LOG_INFO << item.first << "   " << item.second;
            }
        }


    };// MapUtil


/// @note 前向声明
    template<typename... Args>
    struct Impl;

/// @note 基本定义
    template<typename First, typename... Args>
    struct Impl<First, Args...> {
        /// @note 消息类型名字：融合了参数名字的字符串
        static std::string name() {
            return std::string(typeid(First).name()) + " " + Impl<Args...>::name();
        }
    };

/// @note 递归终止
    template<>
    struct Impl<> {
        static std::string name() {
            return "";
        }
    };

/// @note 返回该类型名字
    template<typename... Args>
    std::string type_name() {
        return Impl<Args...>::name();
    }

    template<typename R = void>
    class MessageBus : boost::noncopyable {
    public:
        // 注册

        /// @note 非成员函数
        template<class... Args, class F, class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type>
        void Attach(const std::string &strKey, F &&f) {
            std::function<R(Args...)> fn = [&](Args... args) { return f(std::forward<Args>(args)...); };
            m_map.insert(std::make_pair(strKey + type_name<Args...>(), std::move(fn)));
        }

        /// @note 非 const 成员函数 —— R (C::*f)(DArgs...)
        template<class... Args, class C, class... DArgs, class P>
        void Attach(const std::string &strKey, R (C::*f)(DArgs...), P &&p) {
            std::function<R(Args...)> fn = [&, f](Args... args) { return (*p.*f)(std::forward<Args>(args)...); };
            m_map.insert(std::make_pair(strKey + type_name<Args...>(), std::move(fn)));
        }

        /// @note const 成员函数 —— R (C::*f)(DArgs...) const
        template<class... Args, class C, class... DArgs, class P>
        void Attach(const std::string &strKey, R (C::*f)(DArgs...) const, P &&p) {
            std::function<R(Args...)> fn = [&, f](Args... args) { return (*p.*f)(std::forward<Args>(args)...); };
            m_map.insert(std::make_pair(strKey + type_name<Args...>(), std::move(fn)));
        }

        // @note 广播消息，主题和参数可以确定一个消息, 所有的消息接收者都将收到并处理该消息
        template<typename... Args>
        void SendReq(const std::string &strTopic, Args... args) {
            auto range = m_map.equal_range(strTopic + type_name<Args...>());
            for (auto it = range.first; it != range.second; it++) {
                std::function<R(Args...)> f = boost::any_cast<std::function<R(Args...)>>(it->second);
                f(args...);
            }
        }

#ifdef WIN32

        // @note 移除消息
            template<typename... Args>
            void Remove(const std::string &strTopic) {
                std::string strMsgType = type_name<Args...>();
                auto range = m_map.equal_range(strTopic + strMsgType);
                m_map.erase(range.first, range.second);
            }

#endif
    private:
        std::multimap<std::string, boost::any> m_map;

    };

/**
 * @brief 自旋锁
 * atomic_flag是原子操作的，
 * 获得锁后会把此变量置为true，
 * 另外一个线程就会因为flag=true而一直在while处执行循环，
 * 直到获得锁的线程将锁释放(将flag置为false)
 */
    class SpinlockMutex/* : public NonCopyable */{
    public:
        SpinlockMutex() = default;

        void lock() {
            while (flag.test_and_set(std::memory_order_acquire));
        }

        void unlock() {
            flag.clear(std::memory_order_release);
        }

    private:
        std::atomic_flag flag;
    };

// 使用C++11的原子操作实现自旋锁（默认内存序，memory_order_seq_cst）
    class spin_mutex {
        // flag对象所封装的bool值为false时，说明自旋锁未被线程占有。
        std::atomic<bool> flag = ATOMIC_VAR_INIT(false);
    public:
        spin_mutex() = default;

        spin_mutex(const spin_mutex &) = delete;

        spin_mutex &operator=(const spin_mutex &) = delete;

        void lock() {
            bool expected = false;
            // CAS原子操作。判断flag对象封装的bool值是否为期望值(false)，若为bool值为false，与期望值相等，说明自旋锁空闲。
            // 此时，flag对象封装的bool值写入true，CAS操作成功，结束循环，即上锁成功。
            // 若bool值为为true，与期望值不相等，说明自旋锁被其它线程占据，即CAS操作不成功。然后，由于while循环一直重试，直到CAS操作成功为止。
            while (!flag.compare_exchange_strong(expected, true)) {
                expected = false;
            }
        }

        void unlock() {
            flag.store(false);
        }
    };

    class spin_lock {
    public:
        spin_lock() noexcept {
            v_.clear();
        }

        bool try_lock() noexcept {
            return !v_.test_and_set(std::memory_order_acquire);
        }

        void lock() noexcept {
            for (unsigned k = 0; !try_lock(); ++k) {
                if (k < 16) {
                    std::this_thread::yield();
                } else if (k < 32) {
                    std::this_thread::sleep_for(std::chrono::milliseconds(0));
                } else {
                    std::this_thread::sleep_for(std::chrono::milliseconds(1));
                }
            }
        }

        void unlock() noexcept {
            v_.clear(std::memory_order_release);
        }

    public:
        std::atomic_flag v_;
    };


// 读优先
    class readWriteLock {
    private:
        std::shared_mutex readMtx;
        std::mutex writeMtx;
        int readCnt; // 已加读锁个数
    public:
        readWriteLock() : readCnt(0) {}

        void readLock() {
            readMtx.lock();
            if (++readCnt == 1) {
                writeMtx.lock();  // 存在线程读操作时，写加锁（只加一次）
            }
            readMtx.unlock();
        }

        void readUnlock() {
            readMtx.lock();
            if (--readCnt == 0) { // 没有线程读操作时，释放写锁
                writeMtx.unlock();
            }
            readMtx.unlock();
        }

        void writeLock() {
            writeMtx.lock();
        }

        void writeUnlock() {
            writeMtx.unlock();
        }
    };

/**
 * @brief 自动析构锁
 */
    template<typename Mutex>
    class MutexGuard /*: public NonCopyable*/ {
    public:
        explicit MutexGuard(Mutex &mux)
                : _mutex(mux) {
            _mutex.lock();
        }

        ~MutexGuard() {
            _mutex.unlock();
        }

    private:
        Mutex &_mutex;                // 锁封装
    };

// 信号量
    class semaphore {
    public:
        explicit semaphore(size_t initial = 0) {
#if defined(HAVE_SEM)
            sem_init(&_sem, 0, initial);
#else
            _count = 0;
#endif
        }

        ~semaphore() {
#if defined(HAVE_SEM)
            sem_destroy(&_sem);
#endif
        }

        // 取消阻止
        void post(size_t n = 1) {
#if defined(HAVE_SEM)
            while (n--) {
                        sem_post(&_sem);
                    }
#else
            std::unique_lock<std::recursive_mutex> lock(_mutex);
            _count += n;
            if (n == 1) {
                _condition.notify_one();
            } else {
                _condition.notify_all();
            }
#endif
        }

        // 阻止线程
        void wait() {
#if defined(HAVE_SEM)
            sem_wait(&_sem);
#else
            std::unique_lock<std::recursive_mutex> lock(_mutex);
            while (_count == 0) {
                _condition.wait(lock);
            }
            --_count;
#endif
        }

    private:
#if defined(HAVE_SEM)
        sem_t _sem;
#else
        size_t _count;
        std::recursive_mutex _mutex;
        std::condition_variable_any _condition;
#endif
    };

    template<typename T>
    class scoped_ptr {
    public:
        // Constructor.
        explicit scoped_ptr(T *p = 0)
                : p_(p) {
        }

        // Destructor.
        ~scoped_ptr() {
            delete p_;
        }

        // Access.
        T *get() {
            return p_;
        }

        // Access.
        T *operator->() {
            return p_;
        }

        // Dereference.
        T &operator*() {
            return *p_;
        }

        // Reset pointer.
        void reset(T *p = 0) {
            delete p_;
            p_ = p;
        }

        // Release ownership of the pointer.
        T *release() {
            T *tmp = p_;
            p_ = 0;
            return tmp;
        }

    private:
        // Disallow copying and assignment.
        scoped_ptr(const scoped_ptr &);

        scoped_ptr &operator=(const scoped_ptr &);

        T *p_;
    };

//flat_map to std::map
    template<typename R>
    class RangeUtils {
    public:
        typedef typename R::value_type value_type;

        explicit RangeUtils(R &range) {
            this->m_range = range;
        }

        ~RangeUtils() = default;

        template<typename key_type, typename Fn>
        auto group_by(const Fn &f) ->
        std::multimap<key_type, value_type> {

            std::multimap<key_type, value_type> mymap;
            std::for_each(
                    begin(m_range),
                    end(m_range),
                    [&mymap, &f](value_type item) {
                        mymap.insert(std::make_pair(f(item), item));
                    }
            );
            return mymap;
        }

        /// @note 传两个函数对象
        template<typename key_type, typename value_type_n, typename KeyFn, typename ValueFn>
        auto group_by(const KeyFn &fnk, const ValueFn &fnv) ->
        std::multimap<key_type,
                value_type_n> {

            std::multimap<key_type, value_type_n> mymap;
            std::for_each(
                    begin(m_range),
                    end(m_range),
                    [&mymap, &fnk, &fnv](const value_type &item) {
                        key_type key = fnk(item);
                        value_type_n val = fnv(item);
                        mymap.insert(std::make_pair(key, val));
                    }
            );
            return mymap;
        }

        /// @note 传一个函数对象
        /// 以该函数对象的返回值作为键值
        /// 最终返回一个存有键值对的 multimap
        template<typename Fn>
        auto group_by(const Fn &f) ->
        std::multimap<typename std::invoke_result_t<Fn(value_type)>::type, value_type> {
            //decltype(f(*((value_type*)0))),f((value_type&)nullptr)

            /// @note 定义推测的键值类型
            typedef typename std::invoke_result_t<Fn(value_type)>::type ketype;
            //typedef decltype(std::declval<Fn>()(std::declval<value_type>())) ketype;
            //typedef decltype(f(value_type())) ketype;

            /// @note 遍历 m_range （比如 vector 里的 Person ），并构造键值对插入 mymap
            std::multimap<ketype, value_type> mymap;
            std::for_each(
                    begin(m_range),
                    end(m_range),
                    [&mymap, &f](value_type item) {
                        mymap.insert(std::make_pair(f(item), item));
                    }
            );
            return mymap;
        }

        /// @note 传两个函数对象
        template<typename KeyFn, typename ValueFn>
        auto group_by(const KeyFn &fnk, const ValueFn &fnv) ->
        std::multimap<typename std::invoke_result_t<KeyFn(value_type)>::type,
                typename std::invoke_result_t<ValueFn(value_type)>::type> {

            typedef typename std::invoke_result_t<KeyFn(value_type)>::type ketype;
            typedef typename std::invoke_result_t<ValueFn(value_type)>::type valype;

            /// @note 遍历 m_range ，并构造键值对插入 mymap
            std::multimap<ketype, valype> mymap;
            std::for_each(
                    begin(m_range),
                    end(m_range),
                    [&mymap, &fnk, &fnv](const value_type &item) {
                        ketype key = fnk(item);
                        valype val = fnv(item);
                        mymap.insert(std::make_pair(key, val));
                    }
            );
            return mymap;
        }

    private:
        R m_range;
    };


//禁止拷贝基类
    class NonCopyable {
    public:
        NonCopyable() = default;

        NonCopyable(const NonCopyable &) = delete;

        NonCopyable &operator=(const NonCopyable &) = delete;

        NonCopyable &operator=(NonCopyable &&that) = delete;
    };

/**
 *
 *     std::shared_ptr<void> auto_free(nullptr, [&i](void *)
 *                                   {
 *                                       LOG_INFO << i;
 *                                   }
 *   );
 *    可用共享指针替代
  */

    class OnceToken : public NonCopyable {
    public:
        using task = std::function<void(void)>;

        template<typename FUNC>
        explicit OnceToken(const FUNC &onConstructed, task onDestructed = nullptr) {
            onConstructed();
            _onDestructed = std::move(onDestructed);
        }

        explicit OnceToken(std::nullptr_t, task onDestructed = nullptr) {
            _onDestructed = std::move(onDestructed);
        }

        ~OnceToken() {
            if (_onDestructed) {
                _onDestructed();
            }
        }

    public:
        OnceToken() = delete;

        OnceToken(const OnceToken &) = delete;

        OnceToken(OnceToken &&) = delete;

        OnceToken &operator=(const OnceToken &) = delete;

        OnceToken &operator=(OnceToken &&) = delete;

    private:
        task _onDestructed;
    };


//对象安全的构建和析构
//构建后执行onCreate函数
//析构前执行onDestory函数
//在函数onCreate和onDestory中可以执行构造或析构中不能调用的方法，比如说shared_from_this或者虚函数
    class Creator {
    public:
        template<typename C, typename ...ArgsType>
        static std::shared_ptr<C> create(ArgsType &&...args) {
            std::shared_ptr<C> ret(new C(std::forward<ArgsType>(args)...), [](C *ptr) {
                ptr->onDestory();
                delete ptr;
            });
            ret->onCreate();
            return ret;
        }

    private:
        Creator() = default;

        ~Creator() = default;
    };

/**
 * @brief 单例模式封装类
 * @details T 类型
 */
    template<class T>
    class Singleton {
    public:
        /**
         * @brief 返回单例裸指针
         */
        static T *GetInstance() {
            static T v;
            return &v;
        }
    };

/**
 * @brief 单例模式智能指针封装类
 * @details T 类型
 */
    template<class T>
    class SingletonPtr {
    public:
        /**
         * @brief 返回单例智能指针
         */
        static std::shared_ptr<T> GetInstance() {
            static std::shared_ptr<T> v(new T);
            return v;
        }
    };
/*
    *//**
    * @brief a factory template class
    * @tparam unique
    * @tparam product_base
    * @tparam products
    * @see https://hedzr.com/c++/algorithm/cxx17-factory-pattern/
    *//*
    template<typename product_base, typename... products>
    class factory final {
    public:
#if defined(_MSC_VER)
        using string = std::string; // or std::string_view
#else
        using string = std::string_view;
#endif
        template<typename T>
        struct clz_name_t {
            string id = debug::type_name<T>();
            T data;
        };
        using named_products = std::tuple<clz_name_t<products>...>;
        // using _T = typename std::conditional<unique, std::unique_ptr<product_base>, std::shared_ptr<product_base>>::type;

        template<typename... Args>
        static auto create(const string &id, Args &&...args) {
            std::unique_ptr<product_base> result{};

            std::apply([](auto &&...it) {
                           ((static_check<decltype(it.data)>()), ...);
                       },
                       named_products{});

            std::apply([&](auto &&...it) {
                           ((it.id == id ? result = std::make_unique<decltype(it.data)>(args...) : result), ...);
                       },
                       named_products{});
            return result;
        }
        template<typename... Args>
        static std::shared_ptr<product_base> make_shared(const string &id, Args &&...args) {
            std::shared_ptr<product_base> ptr = create(id, args...);
            return ptr;
        }
        template<typename... Args>
        static std::unique_ptr<product_base> make_unique(const string &id, Args &&...args) {
            return create(id, args...);
        }
        template<typename... Args>
        static product_base *create_nacked_ptr(const string &id, Args &&...args) {
            return create(id, args...).release();
        }

    private:
        template<typename product>
        static void static_check() {
            static_assert(std::is_base_of<product_base, product>::value, "all products must inherit from product_base");
        }
    }; // class factory*/

/**
* @brief a factory template class
* @tparam unique
* @tparam product_base
* @tparam products
* @see https://hedzr.com/c++/algorithm/cxx17-factory-pattern/
*/
    template<typename product_base, typename... products>
    class factory final {
    public:
#if defined(_MSC_VER)
        using string = std::string; // or std::string_view
#else
        using string = std::string_view;
#endif

        template<typename T>
        struct clz_name_t {
            string id = boost::typeindex::type_id_with_cvr<T>().pretty_name();
            T data;
        };
        using named_products = std::tuple<clz_name_t<products>...>;
        // using _T = typename std::conditional<unique, std::unique_ptr<product_base>, std::shared_ptr<product_base>>::type;

        template<typename... Args>
        static auto create(const string &id, Args &&...args) {
            std::unique_ptr<product_base> result{};

            std::apply([](auto &&...it) {
                           ((static_check<decltype(it.data)>()), ...);
                       },
                       named_products{});

            std::apply([&](auto &&...it) {
                           ((it.id == id ? result = std::make_unique<decltype(it.data)>(args...) : result), ...);
                       },
                       named_products{});
            return result;
        }

        template<typename... Args>
        static std::shared_ptr<product_base> make_shared(const string &id, Args &&...args) {
            std::shared_ptr<product_base> ptr = create(id, args...);
            return ptr;
        }

        template<typename... Args>
        static std::unique_ptr<product_base> make_unique(const string &id, Args &&...args) {
            return create(id, args...);
        }

        template<typename... Args>
        static product_base *create_nacked_ptr(const string &id, Args &&...args) {
            return create(id, args...).release();
        }

    private:
        template<typename product>
        static void static_check() {
            static_assert(std::is_base_of<product_base, product>::value, "all products must inherit from product_base");
        }
    }; // class factory


    template<class T>
    inline bool compare_vector_values(std::vector<T> const &v1, std::vector<T> const &v2) {
        bool not_ok = false;
        if (v1.size() == v2.size()) {
            for (std::size_t i = 0; i < v1.size(); i++) {
                if (std::strcmp(v1[i], v2[i]) != 0) {
                    not_ok = true;
                    break;
                }
            }
        } else {
            not_ok = true;
        }
        return (not_ok == false);
    }

    class StringUtil {
    public:

        /// @brief 是否是整型数据
        static bool isInteger(const std::string &str) {
            for (size_t i = 0; i < str.length(); i++) {
                if (str[i] > '9' || str[i] < '0') {
                    return false;
                }
            }
            return true;

        }

        /// @brief 转成小写字母
        static std::string toLower(std::string &str) {
            for (std::string::size_type i = 0; i < str.length(); ++i)
                if (str[i] >= 'A' && str[i] <= 'Z') {
                    str[i] += 0x20;
                }
            return str;
        }

        /// @brief 转成大写字母
        static std::string toUpper(std::string &str) {
            for (std::string::size_type i = 0; i < str.length(); ++i)
                if (str[i] >= 'a' && str[i] <= 'z') {
                    str[i] -= 0x20;
                }
            return str;
        }


        /// @brief 字符是不是字母
        static bool charIsLetter(char c) {
            if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
                return true;
            }
            return false;
        }


        /**
         * @brief 向左修剪
         * @param str 源字符串
         * @param token 条件字符串
         * @return 裁剪后的字符串
         */
        static std::string TrimLeft(const std::string &str, const std::string &token = " ") {
            std::string t = str;
            t.erase(0, t.find_first_not_of(token));
            return t;
        }

        /**
         * @brief 向右修剪
         * @param str 源字符串
         * @param token 条件字符串
         * @return 裁剪后的字符串
         */
        static std::string TrimRight(const std::string &str, const std::string &token = " ") {
            std::string t = str;
            t.erase(t.find_last_not_of(token) + 1);
            return t;
        }

        /**
         * @brief 根据字符同时 左右修剪，默认整理空格
         * @param str 源字符串
         * @param token 条件字符串
         * @return 裁剪后的字符串
         */
        static std::string Trim(const std::string &str, const std::string &token = " ") {
            std::string t = str;
            t.erase(0, t.find_first_not_of(token));
            t.erase(t.find_last_not_of(token) + 1);
            return t;
        }

        /**
         * @brief 转大写
         * @param str 源字符串
         * @return 转换后的字符串
         */
        static std::string ToLower(const std::string &str) {
            std::string t = str;
            std::transform(t.begin(), t.end(), t.begin(), ::tolower);
            return t;
        }

        /**
         * @brief 转小写
         * @param str 源字符串
         * @return 转换后的字符串
         */
        static std::string ToUpper(const std::string &str) {
            std::string t = str;
            std::transform(t.begin(), t.end(), t.begin(), ::toupper);
            return t;
        }

        /**
         * @brief 当前的字符是否以字串开头
         * @param str 源字符串
         * @param subStr 子串
         * @return bool
         */
        static bool StartsWith(const std::string &str, const std::string &subStr) {
            return str.find(subStr) == 0;
        }

        /**
         * @brief 当前的字符是以字串结尾
         * @param str 源字符串
         * @param subStr 字串
         * @return bool
         */
        static bool EndsWith(const std::string &str, const std::string &substr) {
            return str.rfind(substr) == (str.length() - substr.length());
        }

        /**
         * @brief 忽略大小写匹配是否相等
         * @param str1 比较1
         * @param str2 比较2
         * @return bool
         */
        static bool EqualsIgnoreCaseSample(const std::string &str1, const std::string &str2) {
            return ToLower(str1) == ToLower(str2);
        }

        /// @brief 两字符串是否相等，忽略大小写
        static bool EqualsIgnoreCase(const std::string &s1, const std::string &s2) {
            if (s1.length() != s2.length()) {
                return false;
            }

            for (std::string::size_type i = 0; i < s1.length(); ++i) {
                if (s1[i] == s2[i]) {
                    continue;
                }
                if (!charIsLetter(s1[i]) || !charIsLetter(s2[i])) {
                    return false;
                }
                if (0x20 != abs(s1[i] - s2[i])) {
                    return false;
                }
            }
            return true;
        }

        /**
         * @brief 分割字符串
         * @param str 源字串
         * @param delimiter 分隔符
         * @return std::vector
         */
        static std::vector<std::string> Split(const std::string &str, const std::string &delimiter) {
            char *save = nullptr;
#ifdef _WIN32
            char *token = strtok_s(const_cast<char *>(str.c_str()), delimiter.c_str(), &save);
#else
            char *token = strtok_r(const_cast<char *>(str.c_str()), delimiter.c_str(), &save);
#endif
            std::vector<std::string> result;
            while (token != nullptr) {
                result.emplace_back(token);
#ifdef _WIN32
                token = strtok_s(nullptr, delimiter.c_str(), &save);
#else
                token = strtok_r(nullptr, delimiter.c_str(), &save);
#endif
            }
            return result;
        }

        static void Strtok(const std::string &str, char separator, std::vector<std::string> &arr) {
            size_t pos = 0;
            size_t newPos = 0;

            while (std::string::npos != pos) {
                pos = str.find_first_of(separator, newPos);
                if (std::string::npos == pos) { // 结束了
                    if (pos > newPos) {
                        arr.push_back(str.substr(newPos, pos - newPos));
                    }
                    break;
                } else {
                    if (pos > newPos) {
                        arr.push_back(str.substr(newPos, pos - newPos));
                    }
                    newPos = pos + 1;
                }
            }
        }

        static std::vector<std::string> Strtok(const std::string &str, char separator) {
            size_t pos = 0;
            size_t newPos = 0;
            std::vector<std::string> arr;

            while (std::string::npos != pos) {
                pos = str.find_first_of(separator, newPos);
                if (std::string::npos == pos) { // 结束了
                    if (pos > newPos) {
                        arr.push_back(str.substr(newPos, pos - newPos));
                    }
                    break;
                } else {
                    if (pos > newPos) {
                        arr.push_back(str.substr(newPos, pos - newPos));
                    }
                    newPos = pos + 1;
                }
            }
            return arr;
        }

        /**
         * @brief 字串是否包含在源串中
         * @param str 源串
         * @param token 查找串
         * @return bool
         */
        static bool Contains(const std::string &str, const std::string &token) {
            return str.find(token) != std::string::npos;
        }

        // 类型转换 简化调用
        template<typename To, typename From>
        static To cast(const From &from) {
            return converter<To, From>::convert(from);
        }

    private:
        // 模板特化定义
        template<typename To, typename From>
        struct converter {
        };

        // 转换到int类型
        template<typename From>
        struct converter<int, From> {
            static int convert(const std::string &from) { return std::atoi(from.c_str()); }

            static int convert(const char *from) { return std::atoi(from); }
        };

        // 转换到long类型
        template<typename From>
        struct converter<long, From> {
            static long convert(const std::string &from) { return std::atol(from.c_str()); }

            static long convert(const char *from) { return std::atol(from); }
        };

        // 转换到long long类型
        template<typename From>
        struct converter<long long, From> {
            static long long convert(const std::string &from) { return std::atoll(from.c_str()); }

            static long long convert(const char *from) { return std::atoll(from); }
        };

        // 转换到double类型
        template<typename From>
        struct converter<double, From> {
            static double convert(const std::string &from) { return std::atof(from.c_str()); }

            static double convert(const char *from) { return std::atof(from); }
        };

        // 转换到float类型
        template<typename From>
        struct converter<float, From> {
            static float convert(const std::string &from) { return static_cast<float>(std::atof(from.c_str())); }

            static float convert(const char *from) { return static_cast<float>(std::atof(from)); }
        };

        // 转换到bool类型
        template<typename From>
        struct converter<bool, From> {
            static bool convert(int from) { return from > 0; }

            static bool convert(const std::string from) { return std::atoi(from.c_str()) > 0; }
        };

        // 转换到string类型
        template<typename From>
        struct converter<std::string, From> {
            static std::string convert(int from) { return std::to_string(from); }

            static std::string convert(double from) { return std::to_string(from); }

            static std::string convert(float from) { return std::to_string(from); }

            static std::string convert(const std::string &from) { return from; }

            static std::string convert(const char *from) { return from; }

            static std::string convert(char from) { return std::string(&from); }
        };
    };// StringUtil

    class SysUtil {
    public:
        static void MSleep(uint32_t msec) {
#ifdef WIN32
            ::Sleep(msec);
#else
            usleep(msec * 1000);
#endif
        }
    };

    template<typename T>
    class SafeQueue {
    private:
        std::queue<T> m_queue;
        std::mutex m_mutex;

    public:
        SafeQueue() {}

        SafeQueue(SafeQueue &other) {}

        ~SafeQueue() {}

        bool empty() {
            std::unique_lock<std::mutex> lock(m_mutex);
            return m_queue.empty();
        }

        int size() {
            std::unique_lock<std::mutex> lock(m_mutex);
            return m_queue.size();
        }

        void enqueue(T &t) {
            std::unique_lock<std::mutex> lock(m_mutex);
            m_queue.push(t);
        }

        bool dequeue(T &t) {
            std::unique_lock<std::mutex> lock(m_mutex);

            if (m_queue.empty()) {
                return false;
            }
            t = std::move(m_queue.front());

            m_queue.pop();
            return true;
        }
    };


    template<typename Tuple, std::size_t N>
    struct tuple_printer {
        static void print(const Tuple &t) {
            tuple_printer<Tuple, N - 1>::print(t);
            LOG_INFO << ", " << std::get<N - 1>(t);
        }
    };

    template<typename Tuple>
    struct tuple_printer<Tuple, 1> {
        static void print(const Tuple &t) {
            LOG_INFO << std::get<0>(t);
        }
    };

    template<typename... Args>
    void print_tuple(const std::tuple<Args...> &t) {
        tuple_printer<decltype(t), sizeof...(Args)>::print(t);
        LOG_INFO << "\n";
    }

/***********使用流的方式，这里用到了C++14的index_sequence****************/
    template<typename Char, typename Traits, typename Tuple, std::size_t... Index>
    void print_tuple_impl(std::basic_ostream<Char, Traits> &os, const Tuple &t, std::index_sequence<Index...>) {
        using swallow = int[]; // guaranties left to right order
        (void) swallow{0, (void(os << (Index == 0 ? "" : ", ") << std::get<Index>(t)), 0)...};
    }

    template<typename Char, typename Traits, typename... Args>
    decltype(auto) operator<<(std::basic_ostream<Char, Traits> &os, const std::tuple<Args...> &t) {
        os << "(";
        print_tuple_impl(os, t, std::index_sequence_for<Args...>{});
        return os << ")";
    }

/***********将std::array转换成std::tuple，这里用到了C++14的index_sequence****************/
    template<typename Array, std::size_t... Index>
    decltype(auto) array2tuple_impl(const Array &a, std::index_sequence<Index...>) {
        return std::make_tuple(a[Index]...);
    }

    template<typename T, std::size_t N>
    decltype(auto) array2tuple(const std::array<T, N> &a) {
        return array2tuple_impl(a, std::make_index_sequence<N>{});
    }

/***********通过元素类型获取元素的值****************/
    template<typename T, std::size_t N, typename... Args>
    struct index_of;

    template<typename T, std::size_t N, typename... Args>
    struct index_of<T, N, T, Args...> : std::integral_constant<int, N> {
    };

    template<typename T, std::size_t N, typename U, typename... Args>
    struct index_of<T, N, U, Args...> : std::integral_constant<int, index_of<T, N + 1, Args...>::value> {
    };

    template<typename T, std::size_t N>
    struct index_of<T, N> : std::integral_constant<int, -1> {
    };

    template<typename T, typename... Args>
    T get_element_by_type(const std::tuple<Args...> &t) {
        return std::get<index_of<T, 0, Args...>::value>(t);
    }

/***********通过std::tuple作为参数调用函数****************/
    template<typename Function, typename Tuple, std::size_t... Index>
    decltype(auto) invoke_impl(Function &&func, Tuple &&t, std::index_sequence<Index...>) {
        return func(std::get<Index>(std::forward<Tuple>(t))...);
    }

    template<typename Function, typename Tuple>
    decltype(auto) invoke(Function &&func, Tuple &&t) {
        constexpr auto size = std::tuple_size<typename std::decay<Tuple>::type>::value;
        return invoke_impl(std::forward<Function>(func), std::forward<Tuple>(t), std::make_index_sequence<size>{});
    }

/***********make_from_tuple****************/
    template<typename T, typename Tuple, std::size_t... Index>
    decltype(auto) make_from_tuple_impl(Tuple &&t, std::index_sequence<Index...>) {
        return T{std::get<Index>(std::forward<Tuple>(t))...};
    }

    template<typename T, typename Tuple>
    decltype(auto) make_from_tuple(Tuple &&t) {
        constexpr auto size = std::tuple_size<typename std::decay<Tuple>::type>::value;
        return make_from_tuple_impl<T>(std::forward<Tuple>(t), std::make_index_sequence<size>{});
    }
}
#endif //FAST_EXPERIENCE_UTILS_WARP_HPP
